
#ifndef __COMMAND2_HPP__
#define __COMMAND2_HPP__ 

#include "khan.hpp"
#include "vty.hpp"

typedef enum {
    CMD_TYPE,
    IPV4_ADDR_TYPE,
    IPV4_PREFIX_TYPE,
    INT_RANGE_TYPE,
    HEX_RANGE_TYPE,
    STRING_TYPE,        

    OPT_TYPE,
    MULTI_OPT_TYPE,
    CR_TYPE, 
    ROOT_TYPE
}cmd_type;

/* Completion match types. */
typedef enum match_type 
{
  no_match,
  extend_match,
  ipv4_prefix_match,
  ipv4_match,
  range_match,
  partly_match,
  exact_match,
  string_match
} match_type;

class command2;

typedef boost::shared_ptr<command2> command2_ptr;
typedef command2_ptr    cmd_ptr;

typedef std::list<command2_ptr> cmd_list_t;
typedef cmd_list_t::iterator    cmd_list_iterator;

class command2
: public boost::enable_shared_from_this<command2>, 
private boost::noncopyable
{
public:
    explicit command2();
    explicit command2(std::string cmd, std::string help,
            ExcuteHandle function=NULL);
    ~command2();

    void set_function(ExcuteHandle function) { _function = function; };
    cmd_type get_type() { return _type; }

    std::string get_cmd() { return _cmd; }
    std::string get_help() { return _help; }

    void add_child(command2_ptr& c) { 
        if (!find_child(c->get_cmd(), c))
            _childs.push_back(c); 
    }

    bool is_excutable() { return (_function != NULL); }

    match_type mathed(const std::string& str);

    const cmd_list_t& get_children() { return _childs; }
    bool find_child(const std::string cmd, cmd_ptr& cmdptr) {
        cmd_list_iterator iter = _childs.begin();
        for (; iter != _childs.end(); iter++) {
            if ((*iter)->equal(cmd)) {
                cmdptr = (*iter);
                return true;
            }
        }
        return false;
    }

    int find_children(const std::string& str, cmd_list_t& cmdlist);
    int find_children(match_type type, const std::string& str, cmd_list_t& cmdlist);

    int do_command(const std::string& line, string_vector&  args) 
    {
        if (_function != NULL) {
            PDBG(">>> ME(%s) line: %s\n", _cmd.c_str(), line.c_str());
            PDBG("ok funcation call!!\n");
        }
        return -1;
    }
    int do_command(vty_ptr vty, const std::string& line, string_vector&  args) 
    {
        if (_function != NULL) 
            return _function(vty, line, args);
        return -1;
    };

    bool equal(std::string cmd) {
        if(_cmd.compare(cmd) == 0) return true;
        return false;
    }

private:
    cmd_type _type;
    std::string _cmd;
    std::string _help;
    cmd_list_t _childs;
    ExcuteHandle _function;
    int _min, _max;
};

#endif  /* __COMMAND2_HPP__ */
